#ifndef __RINGBUFF_H__
#define __RINGBUFF_H__

#include <iostream>
#include <sys/types.h>
#include <cstdlib>
#include <cstring>

class ringBuff 
{
  public:
    void initRingBuff(size_t sz)
    {
      size_ = sz;
      buff_ = (char*)malloc(sizeof(char) * sz);
      readpos_ = 0;
      writepos_ = 0;
    }

    void freeRingBuff()
    {
      if(buff_)
        free(buff_);
    }

    void clearRingBuff()
    {
      readpos_ = writepos_ = 0;
    }

    size_t ringBuffReadLen()
    {
      return writepos_ - readpos_;
    }

    size_t ringBuffWriteLen()
    {
      return size_ - writepos_ + readpos_;
    }

    void writeBuff(char* buff, size_t sz)
    {
      if(sz > size_ - writepos_ + readpos_)
        return;//放不下

      //必定有sz空间可以放数据
      //所以可以进行下面的操作
      //得到缓存后面的空间
      size_t l = std::min(sz, size_ - (writepos_ & (size_ -1)));
      if(l)
      {
        //后面放完
        memcpy(buff_ + (writepos_ & (size_ - 1)), buff, l);
      }

      if(sz - l)
      {
        //还需要放，缓存前面肯定有数据
        memcpy(buff_, buff + l, sz - l);
      }
      writepos_ += sz;
    }

    size_t readBuff(char* buff, size_t sz)
    {
      // 得到读取数据的长度
      // 必定有len个数据可以读取，所以可以进行下面的操作
      size_t len = std::min(sz, writepos_ - readpos_);
      // 得到缓存后面可以读取的数据
      size_t l = std::min(len, size_ - (readpos_ & (size_ - 1)));
      memcpy(buff, buff_ + (readpos_ & (size_ - 1)), l);
      if(len - l)
      {
        //得到缓存前面可以读取的长度len - l
        memcpy(buff, buff_, len - l);
      }
      readpos_ += len;
      return len;
    }

  private:
    char* buff_;
    size_t size_;
    //读指针和写指针线性增长
    size_t readpos_;
    size_t writepos_;
};

#endif
